from flask import Blueprint, request, jsonify, current_app, g
from flasgger import swag_from
from app import db
from app.models.order import Order
from app.models.venue import Venue, VenueTimeSlot
from app.models.user import User
from app.utils.response import success_response, error_response
from app.utils.decorators import login_required
from app.utils.order_validator import OrderValidator
from app.utils.time_helper import safe_datetime_format, safe_time_format, safe_date_format
from datetime import datetime, date, timedelta
import traceback

order_bp = Blueprint('user_orders', __name__)

def get_db():
    from app import db
    return db

@order_bp.route('/', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-订单'],
    'summary': '创建订单（小程序端）',
    'description': '''用户创建场馆预约订单，需要在请求头中包含JWT token进行用户认证。

**📋 订单创建流程：**
1. 验证用户身份和权限
2. 检查场馆可用性和时间段
3. 验证订单参数合法性
4. 生成唯一订单号
5. 计算订单金额
6. 创建订单记录

**⚠️ 注意事项：**
- 同一用户30分钟内只能创建3个订单
        - 未支付订单不能超过100个
- 预约时间必须至少提前1小时
- 时间段必须在场馆开放时间内
    ''',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'body',
            'in': 'body',
            'required': True,
            'schema': {
                'type': 'object',
                'required': ['venue_id', 'booking_date', 'start_time', 'end_time'],
                'properties': {
                    'venue_id': {
                        'type': 'integer', 
                        'description': '场馆ID，必须是存在的且状态为开放的场馆',
                        'example': 1
                    },
                    'booking_date': {
                        'type': 'string', 
                        'description': '预约日期，格式：YYYY-MM-DD，必须是今天或以后的日期',
                        'example': '2025-06-27'
                    },
                    'start_time': {
                        'type': 'string', 
                        'description': '开始时间，格式：HH:MM 或 HH:MM:SS，必须在场馆开放时间内',
                        'example': '10:00'
                    },
                    'end_time': {
                        'type': 'string', 
                        'description': '结束时间，格式：HH:MM 或 HH:MM:SS，必须晚于开始时间',
                        'example': '12:00'
                    },
                    'participant_count': {
                        'type': 'integer',
                        'description': '参与人数，可选，默认为1，不能超过场馆容量',
                        'example': 5,
                        'default': 1
                    },
                    'remarks': {
                        'type': 'string', 
                        'description': '备注信息（可选），最大200字符',
                        'example': '请准备篮球和饮用水',
                        'maxLength': 200
                    }
                },
                'examples': {
                    'basic_order': {
                        'summary': '基础订单',
                        'value': {
                            'venue_id': 1,
                            'booking_date': '2025-06-27',
                            'start_time': '10:00',
                            'end_time': '12:00'
                        }
                    },
                    'full_order': {
                        'summary': '完整订单',
                        'value': {
                            'venue_id': 1,
                            'booking_date': '2025-06-27',
                            'start_time': '10:00',
                            'end_time': '12:00',
                            'participant_count': 5,
                            'remarks': '请准备篮球和饮用水'
                        }
                    }
                }
            }
        }
    ],
    'responses': {
        200: {
            'description': '订单创建成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '订单创建成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'order_id': {'type': 'integer', 'description': '订单ID，用于后续操作'},
                            'order_no': {'type': 'string', 'description': '订单号，唯一标识符'},
                            'amount': {'type': 'number', 'description': '订单金额（元）'},
                            'status': {'type': 'string', 'description': '订单状态：未支付'},
                            'payment_required': {'type': 'boolean', 'description': '是否需要支付，通常为true'},
                            'booking_info': {
                                'type': 'object',
                                'description': '预约信息详情',
                                'properties': {
                                    'venue_name': {'type': 'string', 'description': '场馆名称'},
                                    'booking_date': {'type': 'string', 'description': '预约日期'},
                                    'start_time': {'type': 'string', 'description': '开始时间'},
                                    'end_time': {'type': 'string', 'description': '结束时间'}
                                }
                            }
                        }
                    }
                }
            }
        },
        400: {
            'description': '请求参数错误或时间段不可用',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 400},
                    'message': {'type': 'string', 'example': '场馆不存在或时间段不可用'}
                }
            }
        },
        401: {
            'description': 'token验证失败，需要重新登录',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 401},
                    'message': {'type': 'string', 'example': '未授权访问'}
                }
            }
        },
        404: {
            'description': '场馆不存在',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 404},
                    'message': {'type': 'string', 'example': '场馆不存在'}
                }
            }
        }
    }
})
def create_order():
    """创建订单"""
    try:
        data = request.get_json()
        
        # 验证订单创建数据
        validated_data = OrderValidator.validate_order_creation_data(data)
        
        venue_id = validated_data['venue_id']
        booking_date = validated_data['booking_date']
        start_time = validated_data['start_time']
        end_time = validated_data['end_time']
        participant_count = validated_data['participant_count']
        remarks = validated_data['remark']
        
        # 检查用户订单频率
        OrderValidator.check_user_order_frequency(g.current_user_id)
        
        # 检查用户未支付订单数量
        OrderValidator.check_user_unpaid_orders(g.current_user_id)
        
        # 验证场馆可用性
        time_slot = OrderValidator.validate_venue_availability(venue_id, booking_date, start_time, end_time)
        
        # 生成订单号
        order_no = OrderValidator.generate_order_no()
        
        # 计算金额
        amount = time_slot.price
        
        # 获取场馆信息
        venue = Venue.query.get(venue_id)
        
        # 创建订单
        order = Order(
            order_no=order_no,
            user_id=g.current_user_id,
            venue_id=venue_id,
            time_slot_id=time_slot.id,
            reservation_date=booking_date,
            start_time=start_time,
            end_time=end_time,
            amount=amount,
            participant_count=participant_count,
            status=0,  # 0-未支付状态
            remark=remarks
        )
        
        db.session.add(order)
        db.session.flush()  # 获取ID但不提交事务
        order_id = order.id
        db.session.commit()
        
        # 记录订单操作日志
        OrderValidator.log_order_operation(
            operation_type='create_order',
            details={
                'order_id': order_id,
                'user_id': g.current_user_id,
                'order_no': order_no,
                'venue_id': venue_id,
                'booking_date': str(booking_date),
                'amount': float(amount)
            }
        )
        
        return success_response({
            'order_id': order_id,
            'order_no': order_no,
            'amount': float(amount),
            'status': '未支付',
            'payment_required': True,
            'booking_info': {
                'venue_name': venue.name,
                'booking_date': str(booking_date),
                'start_time': str(start_time),
                'end_time': str(end_time)
            }
        }, '订单创建成功')
        
    except ValueError as e:
        # 验证错误
        current_app.logger.warning(f"订单创建验证失败: {str(e)}")
        return error_response(str(e), 400)
        
    except Exception as e:
        current_app.logger.error(f"创建订单失败: {str(e)}")
        current_app.logger.error(f"错误详情: {traceback.format_exc()}")
        db.session.rollback()
        return error_response('创建订单失败', 500)

@order_bp.route('/<int:order_id>', methods=['GET'])
@login_required
@swag_from({
    'tags': ['用户-订单'],
    'summary': '获取订单详情',
    'description': '用户查看订单详细信息',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'order_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '订单ID'
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'id': {'type': 'integer'},
                            'order_no': {'type': 'string'},
                            'amount': {'type': 'number'},
                            'status': {'type': 'integer'},
                            'status_text': {'type': 'string'},
                            'venue': {'type': 'object'},
                            'time_slot': {'type': 'object'},
                            'reservation_date': {'type': 'string'},
                            'participant_count': {'type': 'integer'},
                            'contact_name': {'type': 'string'},
                            'contact_phone': {'type': 'string'},
                            'remark': {'type': 'string'},
                            'created_at': {'type': 'string'}
                        }
                    }
                }
            }
        },
        403: {
            'description': '无权访问'
        },
        404: {
            'description': '订单不存在'
        }
    }
})
def get_order_detail(order_id):
    """获取订单详情"""
    try:
        order = Order.query.get(order_id)
        if not order:
            return error_response('订单不存在', 404)
        
        # 检查订单是否属于当前用户 (处理类型不匹配问题)
        current_user_id = int(g.current_user_id) if isinstance(g.current_user_id, str) else g.current_user_id
        if order.user_id != current_user_id:
            return error_response('无权访问该订单', 403)
        
        # 获取关联的场馆和时间段信息
        venue = Venue.query.get(order.venue_id)
        time_slot = VenueTimeSlot.query.get(order.time_slot_id)
        
        order_data = order.to_dict()
        if venue:
            order_data['venue'] = venue.to_dict()
        if time_slot:
            order_data['time_slot'] = time_slot.to_dict()
        
        return success_response(order_data, '获取成功')
        
    except Exception as e:
        current_app.logger.error(f"获取订单详情失败: {str(e)}")
        return error_response('获取失败', 500)

@order_bp.route('/my', methods=['GET'])
@login_required
@swag_from({
    'tags': ['用户-订单'],
    'summary': '我的订单列表',
    'description': '''用户查看自己的订单列表，支持分页和状态筛选。

**📋 订单状态说明：**
- 0 = 未支付：订单已创建但未完成支付
- 1 = 已支付：订单已支付，等待使用
- 2 = 已取消：订单已被取消
- 3 = 已完成：订单已使用完成
- 4 = 已退款：订单已退款

**🔍 筛选功能：**
- 按订单状态筛选
- 支持分页查询
- 按创建时间倒序排列

**📊 返回数据：**
- 订单基本信息（订单号、金额、状态等）
- 场馆信息（名称、地址等）
- 预约信息（日期、时间段等）
- 创建时间
    ''',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'page',
            'in': 'query',
            'type': 'integer',
            'default': 1,
            'description': '页码，从1开始，用于分页查询',
            'example': 1
        },
        {
            'name': 'per_page',
            'in': 'query',
            'type': 'integer',
            'default': 10,
            'description': '每页数量，建议10-50之间，最大100',
            'example': 10
        },
        {
            'name': 'status',
            'in': 'query',
            'type': 'integer',
            'enum': [0, 1, 2, 3, 4],
            'description': '''订单状态筛选：
            • 0 = 未支付（订单已创建但未完成支付）
            • 1 = 已支付（订单已支付，等待使用）
            • 2 = 已取消（订单已被取消）
            • 3 = 已完成（订单已使用完成）
            • 4 = 已退款（订单已退款）
            不传此参数则查询所有状态的订单''',
            'example': 1
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'description': '订单列表数据',
                        'properties': {
                            'total': {'type': 'integer', 'description': '总记录数'},
                            'page': {'type': 'integer', 'description': '当前页码'},
                            'pages': {'type': 'integer', 'description': '总页数'},
                            'per_page': {'type': 'integer', 'description': '每页数量'},
                            'orders': {
                                'type': 'array',
                                'description': '订单列表',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'id': {'type': 'integer', 'description': '订单ID'},
                                        'order_no': {'type': 'string', 'description': '订单号'},
                                        'amount': {'type': 'number', 'description': '订单金额（元）'},
                                        'status': {'type': 'integer', 'description': '订单状态码'},
                                        'status_text': {'type': 'string', 'description': '订单状态文本'},
                                        'venue_name': {'type': 'string', 'description': '场馆名称'},
                                        'reservation_date': {'type': 'string', 'description': '预约日期'},
                                        'time_slot': {'type': 'string', 'description': '时间段'},
                                        'created_at': {'type': 'string', 'description': '创建时间'},
                                        'user_phone': {'type': 'string', 'description': '用户手机号'}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        401: {
            'description': '未授权访问',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 401},
                    'message': {'type': 'string', 'example': '未授权访问'}
                }
            }
        },
        500: {
            'description': '服务器内部错误',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 500},
                    'message': {'type': 'string', 'example': '获取失败'}
                }
            }
        }
    }
})
def get_my_orders():
    """获取我的订单列表"""
    try:
        current_app.logger.info(f"开始获取用户 {g.current_user_id} 的订单列表")
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 100)
        status_filter = request.args.get('status')
        
        query = Order.query.filter_by(user_id=g.current_user_id)
        current_app.logger.info(f"基础查询构建完成: {str(query)}")

        if status_filter is not None:
            try:
                status_int = int(status_filter)
                query = query.filter_by(status=status_int)
                current_app.logger.info(f"应用状态筛选: status={status_int}")
            except (ValueError, TypeError):
                current_app.logger.warning(f"无效的状态参数: {status_filter}")
        
        pagination = query.order_by(Order.created_at.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )
        current_app.logger.info(f"分页查询完成，共 {pagination.total} 条记录")
        
        orders_data = []
        for order in pagination.items:
            try:
                order_dict = order.to_dict(with_venue=True, with_user=True, with_activity=True)
                orders_data.append(order_dict)
            except Exception as e:
                current_app.logger.error(f"序列化订单 {order.id} 失败: {str(e)}")
                current_app.logger.error(traceback.format_exc())
                # 跳过这个订单，而不是让整个请求失败
                continue
        
        current_app.logger.info(f"成功序列化 {len(orders_data)} 个订单")
        
        return success_response({
            'total': pagination.total,
            'page': page,
            'pages': pagination.pages,
            'per_page': per_page,
            'orders': orders_data
        }, '获取成功')
        
    except Exception as e:
        current_app.logger.error(f"获取用户 {g.current_user_id} 的订单列表失败: {str(e)}")
        current_app.logger.error(traceback.format_exc())
        return error_response('获取失败', 500)

@order_bp.route('/<int:order_id>/cancel', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-订单'],
    'summary': '取消订单',
    'description': '用户取消未支付的订单',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'order_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '订单ID'
        }
    ],
    'responses': {
        200: {
            'description': '取消成功'
        },
        400: {
            'description': '订单状态不允许取消'
        },
        403: {
            'description': '无权操作'
        },
        404: {
            'description': '订单不存在'
        }
    }
})
def cancel_order(order_id):
    """取消订单"""
    try:
        order = Order.query.get(order_id)
        if not order:
            return error_response('订单不存在', 404)
        
        # 检查订单是否属于当前用户
        if str(order.user_id) != str(g.current_user_id):
            return error_response('无权操作该订单', 403)
        
        # 检查订单状态
        if order.status != 0:  # 只有未支付状态的订单可以取消
            return error_response('订单状态不允许取消', 400)
        
        # 更新订单状态为已取消
        order.status = 2
        order.updated_at = datetime.now()
        
        db.session.commit()
        
        return success_response({
            'order_id': order_id,
            'cancel_time': safe_datetime_format(order.updated_at)
        }, '订单已取消')
        
    except Exception as e:
        current_app.logger.error(f"取消订单失败: {str(e)}")
        db.session.rollback()
        return error_response('取消失败', 500)

@order_bp.route('/<int:order_id>/checkin', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-订单'],
    'summary': '签到确认',
    'description': '用户到场后进行签到确认',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'order_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '订单ID'
        },
        {
            'name': 'body',
            'in': 'body',
            'schema': {
                'type': 'object',
                'properties': {
                    'checkin_code': {'type': 'string', 'description': '签到码（可选）'},
                    'location': {
                        'type': 'object',
                        'properties': {
                            'latitude': {'type': 'number'},
                            'longitude': {'type': 'number'}
                        },
                        'description': '签到位置（可选）'
                    }
                }
            }
        }
    ],
    'responses': {
        200: {
            'description': '签到成功'
        },
        400: {
            'description': '签到失败'
        },
        403: {
            'description': '无权操作'
        },
        404: {
            'description': '订单不存在'
        }
    }
})
def checkin_order(order_id):
    """订单签到"""
    try:
        order = Order.query.get(order_id)
        if not order:
            return error_response('订单不存在', 404)
        
        # 检查订单是否属于当前用户 (处理类型不匹配问题)
        current_user_id = int(g.current_user_id) if isinstance(g.current_user_id, str) else g.current_user_id
        if order.user_id != current_user_id:
            return error_response('无权操作该订单', 403)
        
        # 检查订单状态
        if order.status != 1:  # 只有已支付的订单可以签到
            return error_response('订单未支付，无法签到', 400)
        
        # 检查签到时间（只能在预约时间段内签到）
        now = datetime.now()
        reservation_date = order.reservation_date
        start_datetime = datetime.combine(reservation_date, order.start_time)
        end_datetime = datetime.combine(reservation_date, order.end_time)
        
        # 允许提前15分钟签到
        checkin_start = start_datetime - timedelta(minutes=15)
        
        if now < checkin_start:
            return error_response('签到时间未到，请在预约时间前15分钟内签到', 400)
        
        if now > end_datetime:
            return error_response('预约时间已过，无法签到', 400)
        
        # 获取签到信息
        data = request.get_json() or {}
        checkin_code = data.get('checkin_code', '')
        location = data.get('location', {})
        
        # 创建签到记录
        from app.models.checkin_record import CheckinRecord
        checkin_record = CheckinRecord(
            order_id=order_id,
            user_id=g.current_user_id,
            venue_id=order.venue_id,
            checkin_code=checkin_code,
            latitude=location.get('latitude'),
            longitude=location.get('longitude'),
            checkin_time=now
        )
        
        db.session.add(checkin_record)
        
        # 更新订单状态为已完成
        order.status = 3
        order.updated_at = now
        
        db.session.commit()
        
        return success_response({
            'order_id': order_id,
            'checkin_time': safe_datetime_format(now),
            'checkin_record_id': checkin_record.id
        }, '签到成功')
        
    except Exception as e:
        current_app.logger.error(f"订单签到失败: {str(e)}")
        db.session.rollback()
        return error_response('签到失败', 500) 